package xyz.scootaloo.oj.offer

import org.junit.Test
import xyz.scootaloo.console.app.support.Tester
import xyz.scootaloo.oj.ds.helper.CollectionHelper

/**
 * @author flutterdash@qq.com
 * @since 2021/4/11 15:21
 */
class P29 {

    /**
     * 1,  2,  3,  4     -  -  -  -             1, 2, 4, 5
     * 5,  6,  7,  8              |    5, 6, 7, 8
     * 9,  10, 11, 12             |
     * 13, 14, 15, 16    -  -  -  |
     */
    private fun spiralOrder(matrix: Array<IntArray>): IntArray {
        // 空值处理
        if(matrix.isEmpty())
            return IntArray(0)

        // 初始化边界和结果数组
        var left = 0
        var right = matrix[0].size - 1
        var top = 0
        var bottom = matrix.size - 1
        val res = IntArray(matrix[0].size * matrix.size)

        // 结果数组下标
        var index = 0
        while (true) {
            // 从左到右
            // 1. 按照边界打印
            for (i in left..right)
                res[index++] = matrix[top][i]
            // 2. 上边界收缩（下移）
            top++
            // 3. 判断收缩后的上边界和下边界是否相遇
            if (top > bottom)
                break

            // 从上到下
            // 1. 按照边界打印
            for (i in top..bottom)
                res[index++] = matrix[i][right]
            // 2. 右边界收缩（左移）
            right--
            // 3. 判断收缩后的右边界和左边界是否相遇
            if (left > right)
                break

            // 从右到左
            // 1. 按照边界打印
            for (i in right downTo left)
                res[index++] = matrix[bottom][i]
            // 2. 下边界收缩（上移)
            bottom--
            // 3. 判断收缩后的下边界和上边界是否相遇
            if (top > bottom)
                break

            // 从下到上
            // 1. 按照边界打印
            for (i in bottom downTo top)
                res[index++] = matrix[i][left]
            // 2. 左边界收缩（右移）
            left++
            // 3. 判断收缩后的左边界和右边界是否相遇
            if(left > right)
                break
        }
        return res
    }

    @Test
    fun test0() {
        Tester.createTest(this::spiralOrder)
            .addCase(                               // 1
                arrayOf(
                    intArrayOf(1),
                    intArrayOf(2),
                    intArrayOf(3),
                    intArrayOf(4),
                    intArrayOf(5),
            ), intArrayOf(1, 2, 3, 4, 5))
            .addCase(                               // 2
                arrayOf(
                    intArrayOf(1, 2),
                    intArrayOf(3, 4),
                    intArrayOf(5, 6),
                ), intArrayOf(1, 2, 4, 6, 5, 3))
            .addCase(                               // 3
                arrayOf(
                    intArrayOf(1, 2),
                    intArrayOf(3, 4),
                ), intArrayOf(1, 2, 4, 3))
            .addCase(                               // 4
                arrayOf(
                    intArrayOf(1, 2, 3, 4),
                    intArrayOf(5, 6, 7, 8),
                ), intArrayOf(1, 2, 3, 4, 8, 7, 6, 5))
            .addCase(                               // 5
                arrayOf(
                    intArrayOf(1, 2, 3, 4),
                    intArrayOf(5, 6, 7, 8),
                    intArrayOf(9, 10, 11, 12),
                ), intArrayOf(1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7))
            .addCase(                               // 6
                arrayOf(
                    intArrayOf(1, 2, 3, 4),
                    intArrayOf(5, 6, 7, 8),
                    intArrayOf(9, 10, 11, 12),
                    intArrayOf(13, 14, 15, 16),
                ), intArrayOf(1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10))
            .addCase(
                arrayOf(
                    intArrayOf(1, 2, 3),
                    intArrayOf(4, 5, 6),
                    intArrayOf(7, 8, 9),
                    intArrayOf(11, 12, 13, 14),
                ), intArrayOf(1, 2, 3, 6, 9, 14, 13, 12, 11, 7, 4, 5, 8))
            .setMatcher(CollectionHelper::intListMatch)
            .testAndShow()

    }

}
